using Quartz;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
namespace Lcygcc.Infrastructure.Utility
{
	[System.Serializable]
	public class CronExpression : System.ICloneable, System.Runtime.Serialization.IDeserializationCallback
	{
		protected const int Second = 0;
		protected const int Minute = 1;
		protected const int Hour = 2;
		protected const int DayOfMonth = 3;
		protected const int Month = 4;
		protected const int DayOfWeek = 5;
		protected const int Year = 6;
		protected const int AllSpecInt = 99;
		protected const int NoSpecInt = 98;
		protected const int AllSpec = 99;
		protected const int NoSpec = 98;
		private static readonly System.Collections.Generic.Dictionary<string, int> monthMap;
		private static readonly System.Collections.Generic.Dictionary<string, int> dayMap;
		private readonly string cronExpressionString;
		private TimeZoneInfo timeZone;
		[System.NonSerialized]
		protected TreeSet<int> seconds;
		[System.NonSerialized]
		protected TreeSet<int> minutes;
		[System.NonSerialized]
		protected TreeSet<int> hours;
		[System.NonSerialized]
		protected TreeSet<int> daysOfMonth;
		[System.NonSerialized]
		protected TreeSet<int> months;
		[System.NonSerialized]
		protected TreeSet<int> daysOfWeek;
		[System.NonSerialized]
		protected TreeSet<int> years;
		[System.NonSerialized]
		protected bool lastdayOfWeek;
		[System.NonSerialized]
		protected int nthdayOfWeek;
		[System.NonSerialized]
		protected bool lastdayOfMonth;
		[System.NonSerialized]
		protected bool nearestWeekday;
		[System.NonSerialized]
		protected int lastdayOffset;
		[System.NonSerialized]
		protected bool calendardayOfWeek;
		[System.NonSerialized]
		protected bool calendardayOfMonth;
		[System.NonSerialized]
		protected bool expressionParsed;
		public static readonly int MaxYear;
		public string CronExpressionString
		{
			get
			{
				return this.cronExpressionString;
			}
		}
		public virtual TimeZoneInfo TimeZone
		{
			get
			{
				if (this.timeZone == null)
				{
					this.timeZone = TimeZoneInfo.Local;
				}
				return this.timeZone;
			}
			set
			{
				this.timeZone = value;
			}
		}
		static CronExpression()
		{
			CronExpression.monthMap = new System.Collections.Generic.Dictionary<string, int>(20);
			CronExpression.dayMap = new System.Collections.Generic.Dictionary<string, int>(60);
			CronExpression.MaxYear = System.DateTime.Now.Year + 100;
			CronExpression.monthMap.Add("JAN", 0);
			CronExpression.monthMap.Add("FEB", 1);
			CronExpression.monthMap.Add("MAR", 2);
			CronExpression.monthMap.Add("APR", 3);
			CronExpression.monthMap.Add("MAY", 4);
			CronExpression.monthMap.Add("JUN", 5);
			CronExpression.monthMap.Add("JUL", 6);
			CronExpression.monthMap.Add("AUG", 7);
			CronExpression.monthMap.Add("SEP", 8);
			CronExpression.monthMap.Add("OCT", 9);
			CronExpression.monthMap.Add("NOV", 10);
			CronExpression.monthMap.Add("DEC", 11);
			CronExpression.dayMap.Add("SUN", 1);
			CronExpression.dayMap.Add("MON", 2);
			CronExpression.dayMap.Add("TUE", 3);
			CronExpression.dayMap.Add("WED", 4);
			CronExpression.dayMap.Add("THU", 5);
			CronExpression.dayMap.Add("FRI", 6);
			CronExpression.dayMap.Add("SAT", 7);
		}
		public CronExpression(string cronExpression)
		{
			if (cronExpression == null)
			{
				throw new System.ArgumentException("cronExpression cannot be null");
			}
			this.cronExpressionString = cronExpression.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
			this.BuildExpression(cronExpression);
		}
		public virtual bool IsSatisfiedBy(System.DateTimeOffset dateUtc)
		{
			System.DateTimeOffset afterTimeUtc = new System.DateTimeOffset(dateUtc.Year, dateUtc.Month, dateUtc.Day, dateUtc.Hour, dateUtc.Minute, dateUtc.Second, dateUtc.Offset).AddSeconds(-1.0);
			System.DateTimeOffset? timeAfter = this.GetTimeAfter(afterTimeUtc);
			return timeAfter.HasValue && timeAfter.Value.Equals(dateUtc);
		}
		public virtual System.DateTimeOffset? GetNextValidTimeAfter(System.DateTimeOffset date)
		{
			return this.GetTimeAfter(date);
		}
		public virtual System.DateTimeOffset? GetNextInvalidTimeAfter(System.DateTimeOffset date)
		{
			long num = 1000L;
			System.DateTimeOffset dateTimeOffset = new System.DateTimeOffset(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Offset).AddSeconds(-1.0);
			while (num == 1000L)
			{
				System.DateTimeOffset? timeAfter = this.GetTimeAfter(dateTimeOffset);
				if (!timeAfter.HasValue)
				{
					break;
				}
				num = (long)(timeAfter.Value - dateTimeOffset).TotalMilliseconds;
				if (num == 1000L)
				{
					dateTimeOffset = timeAfter.Value;
				}
			}
			return new System.DateTimeOffset?(dateTimeOffset.AddSeconds(1.0));
		}
		public override string ToString()
		{
			return this.cronExpressionString;
		}
		public static bool IsValidExpression(string cronExpression)
		{
			try
			{
				new CronExpression(cronExpression);
			}
			catch (System.FormatException)
			{
				return false;
			}
			return true;
		}
		public static void ValidateExpression(string cronExpression)
		{
			new CronExpression(cronExpression);
		}
		public virtual string GetExpressionSummary()
		{
			System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
			stringBuilder.Append("seconds: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.seconds));
			stringBuilder.Append("\n");
			stringBuilder.Append("minutes: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.minutes));
			stringBuilder.Append("\n");
			stringBuilder.Append("hours: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.hours));
			stringBuilder.Append("\n");
			stringBuilder.Append("daysOfMonth: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.daysOfMonth));
			stringBuilder.Append("\n");
			stringBuilder.Append("months: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.months));
			stringBuilder.Append("\n");
			stringBuilder.Append("daysOfWeek: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.daysOfWeek));
			stringBuilder.Append("\n");
			stringBuilder.Append("lastdayOfWeek: ");
			stringBuilder.Append(this.lastdayOfWeek);
			stringBuilder.Append("\n");
			stringBuilder.Append("nearestWeekday: ");
			stringBuilder.Append(this.nearestWeekday);
			stringBuilder.Append("\n");
			stringBuilder.Append("NthDayOfWeek: ");
			stringBuilder.Append(this.nthdayOfWeek);
			stringBuilder.Append("\n");
			stringBuilder.Append("lastdayOfMonth: ");
			stringBuilder.Append(this.lastdayOfMonth);
			stringBuilder.Append("\n");
			stringBuilder.Append("calendardayOfWeek: ");
			stringBuilder.Append(this.calendardayOfWeek);
			stringBuilder.Append("\n");
			stringBuilder.Append("calendardayOfMonth: ");
			stringBuilder.Append(this.calendardayOfMonth);
			stringBuilder.Append("\n");
			stringBuilder.Append("years: ");
			stringBuilder.Append(this.GetExpressionSetSummary(this.years));
			stringBuilder.Append("\n");
			return stringBuilder.ToString();
		}
		public virtual System.DateTimeOffset? GetTimeAfter(System.DateTimeOffset afterTimeUtc)
		{
			afterTimeUtc = afterTimeUtc.AddSeconds(1.0);
			System.DateTimeOffset dateTimeOffset = CronExpression.CreateDateTimeWithoutMillis(afterTimeUtc);
			dateTimeOffset = TimeZoneInfo.ConvertTime(dateTimeOffset, this.TimeZone);
			bool flag = false;
			while (!flag)
			{
				int num = dateTimeOffset.Second;
				ISortedSet<int> sortedSet = this.seconds.TailSet(num);
				if (sortedSet != null && sortedSet.Count != 0)
				{
					num = sortedSet.First();
				}
				else
				{
					num = this.seconds.First();
					dateTimeOffset = dateTimeOffset.AddMinutes(1.0);
				}
				dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day, dateTimeOffset.Hour, dateTimeOffset.Minute, num, dateTimeOffset.Millisecond, dateTimeOffset.Offset);
				int num2 = dateTimeOffset.Minute;
				int num3 = dateTimeOffset.Hour;
				int num4 = -1;
				sortedSet = this.minutes.TailSet(num2);
				if (sortedSet != null && sortedSet.Count != 0)
				{
					num4 = num2;
					num2 = sortedSet.First();
				}
				else
				{
					num2 = this.minutes.First();
					num3++;
				}
				if (num2 != num4)
				{
					dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day, dateTimeOffset.Hour, num2, 0, dateTimeOffset.Millisecond, dateTimeOffset.Offset);
					dateTimeOffset = CronExpression.SetCalendarHour(dateTimeOffset, num3);
				}
				else
				{
					dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day, dateTimeOffset.Hour, num2, dateTimeOffset.Second, dateTimeOffset.Millisecond, dateTimeOffset.Offset);
					num3 = dateTimeOffset.Hour;
					int num5 = dateTimeOffset.Day;
					num4 = -1;
					sortedSet = this.hours.TailSet(num3);
					if (sortedSet != null && sortedSet.Count != 0)
					{
						num4 = num3;
						num3 = sortedSet.First();
					}
					else
					{
						num3 = this.hours.First();
						num5++;
					}
					if (num3 != num4)
					{
						int num6 = System.DateTime.DaysInMonth(dateTimeOffset.Year, dateTimeOffset.Month);
						if (num5 > num6)
						{
							dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, num6, dateTimeOffset.Hour, 0, 0, dateTimeOffset.Millisecond, dateTimeOffset.Offset).AddDays((double)(num5 - num6));
						}
						else
						{
							dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, num5, dateTimeOffset.Hour, 0, 0, dateTimeOffset.Millisecond, dateTimeOffset.Offset);
						}
						dateTimeOffset = CronExpression.SetCalendarHour(dateTimeOffset, num3);
					}
					else
					{
						dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, dateTimeOffset.Day, num3, dateTimeOffset.Minute, dateTimeOffset.Second, dateTimeOffset.Millisecond, dateTimeOffset.Offset);
						num5 = dateTimeOffset.Day;
						int num7 = dateTimeOffset.Month;
						num4 = -1;
						int num8 = num7;
						bool flag2 = !this.daysOfMonth.Contains(98);
						bool flag3 = !this.daysOfWeek.Contains(98);
						if (flag2 && !flag3)
						{
							sortedSet = this.daysOfMonth.TailSet(num5);
							if (this.lastdayOfMonth)
							{
								if (!this.nearestWeekday)
								{
									num4 = num5;
									num5 = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
									num5 -= this.lastdayOffset;
								}
								else
								{
									num4 = num5;
									num5 = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
									num5 -= this.lastdayOffset;
									System.DateTimeOffset dateTimeOffset2 = new System.DateTimeOffset(dateTimeOffset.Year, num7, num5, 0, 0, 0, dateTimeOffset.Offset);
									int lastDayOfMonth = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
									System.DayOfWeek dayOfWeek = dateTimeOffset2.DayOfWeek;
									if (dayOfWeek == System.DayOfWeek.Saturday && num5 == 1)
									{
										num5 += 2;
									}
									else
									{
										if (dayOfWeek == System.DayOfWeek.Saturday)
										{
											num5--;
										}
										else
										{
											if (dayOfWeek == System.DayOfWeek.Sunday && num5 == lastDayOfMonth)
											{
												num5 -= 2;
											}
											else
											{
												if (dayOfWeek == System.DayOfWeek.Sunday)
												{
													num5++;
												}
											}
										}
									}
									System.DateTimeOffset dateTimeOffset3 = new System.DateTimeOffset(dateTimeOffset2.Year, num7, num5, num3, num2, num, dateTimeOffset.Millisecond, dateTimeOffset.Offset);
									if (dateTimeOffset3.ToUniversalTime() < afterTimeUtc)
									{
										num5 = 1;
										num7++;
									}
								}
							}
							else
							{
								if (this.nearestWeekday)
								{
									num4 = num5;
									num5 = this.daysOfMonth.First();
									System.DateTimeOffset dateTimeOffset4 = new System.DateTimeOffset(dateTimeOffset.Year, num7, num5, 0, 0, 0, dateTimeOffset.Offset);
									int lastDayOfMonth2 = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
									System.DayOfWeek dayOfWeek2 = dateTimeOffset4.DayOfWeek;
									if (dayOfWeek2 == System.DayOfWeek.Saturday && num5 == 1)
									{
										num5 += 2;
									}
									else
									{
										if (dayOfWeek2 == System.DayOfWeek.Saturday)
										{
											num5--;
										}
										else
										{
											if (dayOfWeek2 == System.DayOfWeek.Sunday && num5 == lastDayOfMonth2)
											{
												num5 -= 2;
											}
											else
											{
												if (dayOfWeek2 == System.DayOfWeek.Sunday)
												{
													num5++;
												}
											}
										}
									}
									dateTimeOffset4 = new System.DateTimeOffset(dateTimeOffset4.Year, num7, num5, num3, num2, num, dateTimeOffset.Offset);
									if (dateTimeOffset4.ToUniversalTime() < afterTimeUtc)
									{
										num5 = this.daysOfMonth.First();
										num7++;
									}
								}
								else
								{
									if (sortedSet != null && sortedSet.Count != 0)
									{
										num4 = num5;
										num5 = sortedSet.First();
										int lastDayOfMonth3 = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
										if (num5 > lastDayOfMonth3)
										{
											num5 = this.daysOfMonth.First();
											num7++;
										}
									}
									else
									{
										num5 = this.daysOfMonth.First();
										num7++;
									}
								}
							}
							if (num5 != num4 || num7 != num8)
							{
								if (num7 > 12)
								{
									dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, 12, num5, 0, 0, 0, dateTimeOffset.Offset).AddMonths(num7 - 12);
									continue;
								}
								int num9 = System.DateTime.DaysInMonth(dateTimeOffset.Year, num7);
								if (num5 <= num9)
								{
									dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7, num5, 0, 0, 0, dateTimeOffset.Offset);
									continue;
								}
								dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7, num9, 0, 0, 0, dateTimeOffset.Offset).AddDays((double)(num5 - num9));
								continue;
							}
						}
						else
						{
							if (!flag3 || flag2)
							{
								throw new System.Exception("Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.");
							}
							if (this.lastdayOfWeek)
							{
								int num10 = this.daysOfWeek.First();
								int num11 = (int)(dateTimeOffset.DayOfWeek + 1);
								int num12 = 0;
								if (num11 < num10)
								{
									num12 = num10 - num11;
								}
								if (num11 > num10)
								{
									num12 = num10 + (7 - num11);
								}
								int lastDayOfMonth4 = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
								if (num5 + num12 > lastDayOfMonth4)
								{
									if (num7 == 12)
									{
										dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7 - 11, 1, 0, 0, 0, dateTimeOffset.Offset).AddYears(1);
										continue;
									}
									dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7 + 1, 1, 0, 0, 0, dateTimeOffset.Offset);
									continue;
								}
								else
								{
									while (num5 + num12 + 7 <= lastDayOfMonth4)
									{
										num12 += 7;
									}
									num5 += num12;
									if (num12 > 0)
									{
										dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7, num5, 0, 0, 0, dateTimeOffset.Offset);
										continue;
									}
								}
							}
							else
							{
								if (this.nthdayOfWeek != 0)
								{
									int num13 = this.daysOfWeek.First();
									int num14 = (int)(dateTimeOffset.DayOfWeek + 1);
									int num15 = 0;
									if (num14 < num13)
									{
										num15 = num13 - num14;
									}
									else
									{
										if (num14 > num13)
										{
											num15 = num13 + (7 - num14);
										}
									}
									bool flag4 = false;
									if (num15 > 0)
									{
										flag4 = true;
									}
									num5 += num15;
									int num16 = num5 / 7;
									if (num5 % 7 > 0)
									{
										num16++;
									}
									num15 = (this.nthdayOfWeek - num16) * 7;
									num5 += num15;
									if (num15 < 0 || num5 > this.GetLastDayOfMonth(num7, dateTimeOffset.Year))
									{
										if (num7 == 12)
										{
											dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7 - 11, 1, 0, 0, 0, dateTimeOffset.Offset).AddYears(1);
											continue;
										}
										dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7 + 1, 1, 0, 0, 0, dateTimeOffset.Offset);
										continue;
									}
									else
									{
										if (num15 > 0 || flag4)
										{
											dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7, num5, 0, 0, 0, dateTimeOffset.Offset);
											continue;
										}
									}
								}
								else
								{
									int num17 = (int)(dateTimeOffset.DayOfWeek + 1);
									int num18 = this.daysOfWeek.First();
									sortedSet = this.daysOfWeek.TailSet(num17);
									if (sortedSet != null && sortedSet.Count > 0)
									{
										num18 = sortedSet.First();
									}
									int num19 = 0;
									if (num17 < num18)
									{
										num19 = num18 - num17;
									}
									if (num17 > num18)
									{
										num19 = num18 + (7 - num17);
									}
									int lastDayOfMonth5 = this.GetLastDayOfMonth(num7, dateTimeOffset.Year);
									if (num5 + num19 > lastDayOfMonth5)
									{
										if (num7 == 12)
										{
											dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7 - 11, 1, 0, 0, 0, dateTimeOffset.Offset).AddYears(1);
											continue;
										}
										dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7 + 1, 1, 0, 0, 0, dateTimeOffset.Offset);
										continue;
									}
									else
									{
										if (num19 > 0)
										{
											dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7, num5 + num19, 0, 0, 0, dateTimeOffset.Offset);
											continue;
										}
									}
								}
							}
						}
						dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, dateTimeOffset.Month, num5, dateTimeOffset.Hour, dateTimeOffset.Minute, dateTimeOffset.Second, dateTimeOffset.Offset);
						num7 = dateTimeOffset.Month;
						int num20 = dateTimeOffset.Year;
						num4 = -1;
						if (num20 > CronExpression.MaxYear)
						{
							return null;
						}
						sortedSet = this.months.TailSet(num7);
						if (sortedSet != null && sortedSet.Count != 0)
						{
							num4 = num7;
							num7 = sortedSet.First();
						}
						else
						{
							num7 = this.months.First();
							num20++;
						}
						if (num7 != num4)
						{
							dateTimeOffset = new System.DateTimeOffset(num20, num7, 1, 0, 0, 0, dateTimeOffset.Offset);
						}
						else
						{
							dateTimeOffset = new System.DateTimeOffset(dateTimeOffset.Year, num7, dateTimeOffset.Day, dateTimeOffset.Hour, dateTimeOffset.Minute, dateTimeOffset.Second, dateTimeOffset.Offset);
							num20 = dateTimeOffset.Year;
							sortedSet = this.years.TailSet(num20);
							if (sortedSet == null || sortedSet.Count == 0)
							{
								return null;
							}
							num4 = num20;
							num20 = sortedSet.First();
							if (num20 != num4)
							{
								dateTimeOffset = new System.DateTimeOffset(num20, 1, 1, 0, 0, 0, dateTimeOffset.Offset);
							}
							else
							{
								dateTimeOffset = new System.DateTimeOffset(num20, dateTimeOffset.Month, dateTimeOffset.Day, dateTimeOffset.Hour, dateTimeOffset.Minute, dateTimeOffset.Second, dateTimeOffset.Offset);
								flag = true;
							}
						}
					}
				}
			}
			return new System.DateTimeOffset?(dateTimeOffset.ToUniversalTime());
		}
		public virtual System.DateTimeOffset? GetTimeBefore(System.DateTimeOffset? endTime)
		{
			return null;
		}
		public virtual System.DateTimeOffset? GetFinalFireTime()
		{
			return null;
		}
		protected void BuildExpression(string expression)
		{
			this.expressionParsed = true;
			try
			{
				if (this.seconds == null)
				{
					this.seconds = new TreeSet<int>();
				}
				if (this.minutes == null)
				{
					this.minutes = new TreeSet<int>();
				}
				if (this.hours == null)
				{
					this.hours = new TreeSet<int>();
				}
				if (this.daysOfMonth == null)
				{
					this.daysOfMonth = new TreeSet<int>();
				}
				if (this.months == null)
				{
					this.months = new TreeSet<int>();
				}
				if (this.daysOfWeek == null)
				{
					this.daysOfWeek = new TreeSet<int>();
				}
				if (this.years == null)
				{
					this.years = new TreeSet<int>();
				}
				int num = 0;
				string[] array = expression.Trim().Split(new char[]
				{
					' ',
					'\t',
					'\r',
					'\n'
				}, System.StringSplitOptions.RemoveEmptyEntries);
				string[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					string text = array2[i];
					string text2 = text.Trim();
					if (text2.Length != 0)
					{
						if (num > 6)
						{
							break;
						}
						if (num == 3 && text2.IndexOf('L') != -1 && text2.Length > 1 && text2.IndexOf(",") >= 0)
						{
							throw new System.FormatException("日期中指定L和LW的格式未被支持(0 15 10 L * ? 每月最后一日的上午10:15触发)");
						}
						if (num == 5 && text2.IndexOf('L') != -1 && text2.Length > 1 && text2.IndexOf(",") >= 0)
						{
							throw new System.FormatException("星期中指定L的格式未被支持(0 15 10 ? * 6L每月的最后一个星期五上午10:15触发");
						}
						if (num == 5 && text2.IndexOf('#') != -1 && text2.IndexOf('#', text2.IndexOf('#') + 1) != -1)
						{
							throw new System.FormatException("星期中指定#的格式未被支持(0 15 10 ? * 6#3每月的第三个星期五上午10:15触发)");
						}
						string[] array3 = text2.Split(new char[]
						{
							','
						});
						string[] array4 = array3;
						for (int j = 0; j < array4.Length; j++)
						{
							string s = array4[j];
							this.StoreExpressionVals(0, s, num);
						}
						num++;
					}
				}
				if (num <= 5)
				{
					throw new System.FormatException("Unexpected end of expression.");
				}
				if (num <= 6)
				{
					this.StoreExpressionVals(0, "*", 6);
				}
				ISortedSet<int> set = this.GetSet(5);
				ISortedSet<int> set2 = this.GetSet(3);
				bool flag = !set2.Contains(98);
				bool flag2 = !set.Contains(98);
				if ((!flag || flag2) && (!flag2 || flag))
				{
					throw new System.FormatException("Support for specifying both a day-of-week AND a day-of-month parameter is not implemented.");
				}
			}
			catch (System.FormatException)
			{
				throw;
			}
			catch (System.Exception ex)
			{
				throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Illegal cron expression format ({0})", new object[]
				{
					ex
				}));
			}
		}
		protected virtual int StoreExpressionVals(int pos, string s, int type)
		{
			int num = 0;
			int num2 = this.SkipWhiteSpace(pos, s);
			if (num2 >= s.Length)
			{
				return num2;
			}
			char c = s[num2];
			if (c >= 'A' && c <= 'Z' && !s.Equals("L") && !s.Equals("LW") && !Regex.IsMatch(s, "^L-[0-9]*[W]?"))
			{
				string text = s.Substring(num2, 3);
				int num3 = -1;
				int num4;
				if (type == 4)
				{
					num4 = this.GetMonthNumber(text) + 1;
					if (num4 <= 0)
					{
						throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid Month value: '{0}'", new object[]
						{
							text
						}));
					}
					if (s.Length > num2 + 3)
					{
						c = s[num2 + 3];
						if (c == '-')
						{
							num2 += 4;
							text = s.Substring(num2, 3);
							num3 = this.GetMonthNumber(text) + 1;
							if (num3 <= 0)
							{
								throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid Month value: '{0}'", new object[]
								{
									text
								}));
							}
						}
					}
				}
				else
				{
					if (type != 5)
					{
						throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Illegal characters for this position: '{0}'", new object[]
						{
							text
						}));
					}
					num4 = this.GetDayOfWeekNumber(text);
					if (num4 < 0)
					{
						throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid Day-of-Week value: '{0}'", new object[]
						{
							text
						}));
					}
					if (s.Length > num2 + 3)
					{
						c = s[num2 + 3];
						if (c == '-')
						{
							num2 += 4;
							text = s.Substring(num2, 3);
							num3 = this.GetDayOfWeekNumber(text);
							if (num3 < 0)
							{
								throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid Day-of-Week value: '{0}'", new object[]
								{
									text
								}));
							}
						}
						else
						{
							if (c == '#')
							{
								try
								{
									num2 += 4;
									this.nthdayOfWeek = System.Convert.ToInt32(s.Substring(num2), System.Globalization.CultureInfo.InvariantCulture);
									if (this.nthdayOfWeek < 1 || this.nthdayOfWeek > 5)
									{
										throw new System.Exception();
									}
									goto IL_21D;
								}
								catch (System.Exception)
								{
									throw new System.FormatException("A numeric value between 1 and 5 must follow the '#' option");
								}
							}
							if (c == 'L')
							{
								this.lastdayOfWeek = true;
								num2++;
							}
						}
					}
				}
				IL_21D:
				if (num3 != -1)
				{
					num = 1;
				}
				this.AddToSet(num4, num3, num, type);
				return num2 + 3;
			}
			if (c == '?')
			{
				num2++;
				if (num2 + 1 < s.Length && s[num2] != ' ' && s[num2 + 1] != '\t')
				{
					throw new System.FormatException("Illegal character after '?': " + s[num2]);
				}
				if (type != 5 && type != 3)
				{
					throw new System.FormatException("'?' can only be specified for Day-of-Month or Day-of-Week.");
				}
				if (type == 5 && !this.lastdayOfMonth)
				{
					int num5 = this.daysOfMonth[this.daysOfMonth.Count - 1];
					if (num5 == 98)
					{
						throw new System.FormatException("'?' can only be specified for Day-of-Month -OR- Day-of-Week.");
					}
				}
				this.AddToSet(98, -1, 0, type);
				return num2;
			}
			else
			{
				if (c == '*' || c == '/')
				{
					if (c == '*' && num2 + 1 >= s.Length)
					{
						this.AddToSet(99, -1, num, type);
						return num2 + 1;
					}
					if (c == '/' && (num2 + 1 >= s.Length || s[num2 + 1] == ' ' || s[num2 + 1] == '\t'))
					{
						throw new System.FormatException("'/' must be followed by an integer.");
					}
					if (c == '*')
					{
						num2++;
					}
					c = s[num2];
					if (c == '/')
					{
						num2++;
						if (num2 >= s.Length)
						{
							throw new System.FormatException("Unexpected end of string.");
						}
						num = this.GetNumericValue(s, num2);
						num2++;
						if (num > 10)
						{
							num2++;
						}
						if (num > 59 && (type == 0 || type == 1))
						{
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Increment > 60 : {0}", new object[]
							{
								num
							}));
						}
						if (num > 23 && type == 2)
						{
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Increment > 24 : {0}", new object[]
							{
								num
							}));
						}
						if (num > 31 && type == 3)
						{
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Increment > 31 : {0}", new object[]
							{
								num
							}));
						}
						if (num > 7 && type == 5)
						{
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Increment > 7 : {0}", new object[]
							{
								num
							}));
						}
						if (num > 12 && type == 4)
						{
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Increment > 12 : {0}", new object[]
							{
								num
							}));
						}
					}
					else
					{
						num = 1;
					}
					this.AddToSet(99, -1, num, type);
					return num2;
				}
				else
				{
					if (c == 'L')
					{
						num2++;
						if (type == 3)
						{
							this.lastdayOfMonth = true;
						}
						if (type == 5)
						{
							this.AddToSet(7, 7, 0, type);
						}
						if (type == 3 && s.Length > num2)
						{
							c = s[num2];
							if (c == '-')
							{
								ValueSet value = this.GetValue(0, s, num2 + 1);
								this.lastdayOffset = value.theValue;
								if (this.lastdayOffset > 30)
								{
									throw new System.FormatException("Offset from last day must be <= 30");
								}
								num2 = value.pos;
							}
							if (s.Length > num2)
							{
								c = s[num2];
								if (c == 'W')
								{
									this.nearestWeekday = true;
									num2++;
								}
							}
						}
						return num2;
					}
					if (c < '0' || c > '9')
					{
						throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Unexpected character: {0}", new object[]
						{
							c
						}));
					}
					int num6 = System.Convert.ToInt32(c.ToString(), System.Globalization.CultureInfo.InvariantCulture);
					num2++;
					if (num2 >= s.Length)
					{
						this.AddToSet(num6, -1, -1, type);
						return num2;
					}
					c = s[num2];
					if (c >= '0' && c <= '9')
					{
						ValueSet value2 = this.GetValue(num6, s, num2);
						num6 = value2.theValue;
						num2 = value2.pos;
					}
					num2 = this.CheckNext(num2, s, num6, type);
					return num2;
				}
			}
		}
		protected virtual int CheckNext(int pos, string s, int val, int type)
		{
			int end = -1;
			int num = pos;
			if (num >= s.Length)
			{
				this.AddToSet(val, end, -1, type);
				return num;
			}
			char c = s[pos];
			if (c == 'L')
			{
				if (type != 5)
				{
					throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "'L' option is not valid here. (pos={0})", new object[]
					{
						num
					}));
				}
				if (val < 1 || val > 7)
				{
					throw new System.FormatException("Day-of-Week values must be between 1 and 7");
				}
				this.lastdayOfWeek = true;
				ISortedSet<int> set = this.GetSet(type);
				set.Add(val);
				num++;
				return num;
			}
			else
			{
				if (c == 'W')
				{
					if (type != 3)
					{
						throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "'W' option is not valid here. (pos={0})", new object[]
						{
							num
						}));
					}
					this.nearestWeekday = true;
					if (val > 31)
					{
						throw new System.FormatException("The 'W' option does not make sense with values larger than 31 (max number of days in a month)");
					}
					ISortedSet<int> set2 = this.GetSet(type);
					set2.Add(val);
					num++;
					return num;
				}
				else
				{
					if (c == '#')
					{
						if (type != 5)
						{
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "'#' option is not valid here. (pos={0})", new object[]
							{
								num
							}));
						}
						num++;
						try
						{
							this.nthdayOfWeek = System.Convert.ToInt32(s.Substring(num), System.Globalization.CultureInfo.InvariantCulture);
							if (this.nthdayOfWeek < 1 || this.nthdayOfWeek > 5)
							{
								throw new System.Exception();
							}
						}
						catch (System.Exception)
						{
							throw new System.FormatException("A numeric value between 1 and 5 must follow the '#' option");
						}
						ISortedSet<int> set3 = this.GetSet(type);
						set3.Add(val);
						num++;
						return num;
					}
					else
					{
						if (c == 'C')
						{
							if (type == 5)
							{
								this.calendardayOfWeek = true;
							}
							else
							{
								if (type != 3)
								{
									throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "'C' option is not valid here. (pos={0})", new object[]
									{
										num
									}));
								}
								this.calendardayOfMonth = true;
							}
							ISortedSet<int> set4 = this.GetSet(type);
							set4.Add(val);
							num++;
							return num;
						}
						if (c == '-')
						{
							num++;
							int num2 = System.Convert.ToInt32(s[num].ToString(), System.Globalization.CultureInfo.InvariantCulture);
							end = num2;
							num++;
							if (num >= s.Length)
							{
								this.AddToSet(val, end, 1, type);
								return num;
							}
							c = s[num];
							if (c >= '0' && c <= '9')
							{
								ValueSet value = this.GetValue(num2, s, num);
								int theValue = value.theValue;
								end = theValue;
								num = value.pos;
							}
							if (num >= s.Length || s[num] != '/')
							{
								this.AddToSet(val, end, 1, type);
								return num;
							}
							num++;
							int num3 = System.Convert.ToInt32(s[num].ToString(), System.Globalization.CultureInfo.InvariantCulture);
							num++;
							if (num >= s.Length)
							{
								this.AddToSet(val, end, num3, type);
								return num;
							}
							c = s[num];
							if (c >= '0' && c <= '9')
							{
								ValueSet value2 = this.GetValue(num3, s, num);
								int theValue2 = value2.theValue;
								this.AddToSet(val, end, theValue2, type);
								num = value2.pos;
								return num;
							}
							this.AddToSet(val, end, num3, type);
							return num;
						}
						else
						{
							if (c != '/')
							{
								this.AddToSet(val, end, 0, type);
								num++;
								return num;
							}
							num++;
							int num4 = System.Convert.ToInt32(s[num].ToString(), System.Globalization.CultureInfo.InvariantCulture);
							num++;
							if (num >= s.Length)
							{
								this.AddToSet(val, end, num4, type);
								return num;
							}
							c = s[num];
							if (c >= '0' && c <= '9')
							{
								ValueSet value3 = this.GetValue(num4, s, num);
								int theValue3 = value3.theValue;
								this.AddToSet(val, end, theValue3, type);
								num = value3.pos;
								return num;
							}
							throw new System.FormatException(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Unexpected character '{0}' after '/'", new object[]
							{
								c
							}));
						}
					}
				}
			}
		}
		protected virtual string GetExpressionSetSummary(ISet<int> data)
		{
			if (data.Contains(98))
			{
				return "?";
			}
			if (data.Contains(99))
			{
				return "*";
			}
			System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder();
			bool flag = true;
			foreach (int current in data)
			{
				string value = current.ToString(System.Globalization.CultureInfo.InvariantCulture);
				if (!flag)
				{
					stringBuilder.Append(",");
				}
				stringBuilder.Append(value);
				flag = false;
			}
			return stringBuilder.ToString();
		}
		protected virtual int SkipWhiteSpace(int i, string s)
		{
			while (i < s.Length && (s[i] == ' ' || s[i] == '\t'))
			{
				i++;
			}
			return i;
		}
		protected virtual int FindNextWhiteSpace(int i, string s)
		{
			while (i < s.Length && (s[i] != ' ' || s[i] != '\t'))
			{
				i++;
			}
			return i;
		}
		protected virtual void AddToSet(int val, int end, int incr, int type)
		{
			ISortedSet<int> set = this.GetSet(type);
			if (type == 0 || type == 1)
			{
				if ((val < 0 || val > 59 || end > 59) && val != 99)
				{
					throw new System.FormatException("Minute and Second values must be between 0 and 59");
				}
			}
			else
			{
				if (type == 2)
				{
					if ((val < 0 || val > 23 || end > 23) && val != 99)
					{
						throw new System.FormatException("Hour values must be between 0 and 23");
					}
				}
				else
				{
					if (type == 3)
					{
						if ((val < 1 || val > 31 || end > 31) && val != 99 && val != 98)
						{
							throw new System.FormatException("Day of month values must be between 1 and 31");
						}
					}
					else
					{
						if (type == 4)
						{
							if ((val < 1 || val > 12 || end > 12) && val != 99)
							{
								throw new System.FormatException("Month values must be between 1 and 12");
							}
						}
						else
						{
							if (type == 5 && (val == 0 || val > 7 || end > 7) && val != 99 && val != 98)
							{
								throw new System.FormatException("Day-of-Week values must be between 1 and 7");
							}
						}
					}
				}
			}
			if ((incr != 0 && incr != -1) || val == 99)
			{
				int num = val;
				int num2 = end;
				if (val == 99 && incr <= 0)
				{
					incr = 1;
					set.Add(99);
				}
				if (type == 0 || type == 1)
				{
					if (num2 == -1)
					{
						num2 = 59;
					}
					if (num == -1 || num == 99)
					{
						num = 0;
					}
				}
				else
				{
					if (type == 2)
					{
						if (num2 == -1)
						{
							num2 = 23;
						}
						if (num == -1 || num == 99)
						{
							num = 0;
						}
					}
					else
					{
						if (type == 3)
						{
							if (num2 == -1)
							{
								num2 = 31;
							}
							if (num == -1 || num == 99)
							{
								num = 1;
							}
						}
						else
						{
							if (type == 4)
							{
								if (num2 == -1)
								{
									num2 = 12;
								}
								if (num == -1 || num == 99)
								{
									num = 1;
								}
							}
							else
							{
								if (type == 5)
								{
									if (num2 == -1)
									{
										num2 = 7;
									}
									if (num == -1 || num == 99)
									{
										num = 1;
									}
								}
								else
								{
									if (type == 6)
									{
										if (num2 == -1)
										{
											num2 = CronExpression.MaxYear;
										}
										if (num == -1 || num == 99)
										{
											num = 1970;
										}
									}
								}
							}
						}
					}
				}
				int num3 = -1;
				if (num2 < num)
				{
					switch (type)
					{
					case 0:
						num3 = 60;
						break;
					case 1:
						num3 = 60;
						break;
					case 2:
						num3 = 24;
						break;
					case 3:
						num3 = 31;
						break;
					case 4:
						num3 = 12;
						break;
					case 5:
						num3 = 7;
						break;
					case 6:
						throw new System.ArgumentException("Start year must be less than stop year");
					default:
						throw new System.ArgumentException("Unexpected type encountered");
					}
					num2 += num3;
				}
				for (int i = num; i <= num2; i += incr)
				{
					if (num3 == -1)
					{
						set.Add(i);
					}
					else
					{
						int num4 = i % num3;
						if (num4 == 0 && (type == 4 || type == 5 || type == 3))
						{
							num4 = num3;
						}
						set.Add(num4);
					}
				}
				return;
			}
			if (val != -1)
			{
				set.Add(val);
				return;
			}
			set.Add(98);
		}
		protected virtual ISortedSet<int> GetSet(int type)
		{
			switch (type)
			{
			case 0:
				return this.seconds;
			case 1:
				return this.minutes;
			case 2:
				return this.hours;
			case 3:
				return this.daysOfMonth;
			case 4:
				return this.months;
			case 5:
				return this.daysOfWeek;
			case 6:
				return this.years;
			default:
				return null;
			}
		}
		protected virtual ValueSet GetValue(int v, string s, int i)
		{
			char c = s[i];
			System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(v.ToString(System.Globalization.CultureInfo.InvariantCulture));
			while (c >= '0' && c <= '9')
			{
				stringBuilder.Append(c);
				i++;
				if (i >= s.Length)
				{
					break;
				}
				c = s[i];
			}
			ValueSet valueSet = new ValueSet();
			if (i < s.Length)
			{
				valueSet.pos = i;
			}
			else
			{
				valueSet.pos = i + 1;
			}
			valueSet.theValue = System.Convert.ToInt32(stringBuilder.ToString(), System.Globalization.CultureInfo.InvariantCulture);
			return valueSet;
		}
		protected virtual int GetNumericValue(string s, int i)
		{
			int num = this.FindNextWhiteSpace(i, s);
			string value = s.Substring(i, num - i);
			return System.Convert.ToInt32(value, System.Globalization.CultureInfo.InvariantCulture);
		}
		protected virtual int GetMonthNumber(string s)
		{
			if (CronExpression.monthMap.ContainsKey(s))
			{
				return CronExpression.monthMap[s];
			}
			return -1;
		}
		protected virtual int GetDayOfWeekNumber(string s)
		{
			if (CronExpression.dayMap.ContainsKey(s))
			{
				return CronExpression.dayMap[s];
			}
			return -1;
		}
		protected virtual System.DateTimeOffset? GetTime(int sc, int mn, int hr, int dayofmn, int mon)
		{
			System.DateTimeOffset? result;
			try
			{
				if (sc == -1)
				{
					sc = 0;
				}
				if (mn == -1)
				{
					mn = 0;
				}
				if (hr == -1)
				{
					hr = 0;
				}
				if (dayofmn == -1)
				{
					dayofmn = 0;
				}
				if (mon == -1)
				{
					mon = 0;
				}
				result = new System.DateTimeOffset?(new System.DateTimeOffset(SystemTime.UtcNow().Year, mon, dayofmn, hr, mn, sc, System.TimeSpan.Zero));
			}
			catch (System.Exception)
			{
				result = null;
			}
			return result;
		}
		protected static System.DateTimeOffset CreateDateTimeWithoutMillis(System.DateTimeOffset time)
		{
			return new System.DateTimeOffset(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second, time.Offset);
		}
		protected static System.DateTimeOffset SetCalendarHour(System.DateTimeOffset date, int hour)
		{
			int num = hour;
			if (num == 24)
			{
				num = 0;
			}
			System.DateTimeOffset result = new System.DateTimeOffset(date.Year, date.Month, date.Day, num, date.Minute, date.Second, date.Millisecond, date.Offset);
			if (hour == 24)
			{
				result = result.AddDays(1.0);
			}
			return result;
		}
		protected virtual bool IsLeapYear(int year)
		{
			return System.DateTime.IsLeapYear(year);
		}
		protected virtual int GetLastDayOfMonth(int monthNum, int year)
		{
			return System.DateTime.DaysInMonth(year, monthNum);
		}
		public object Clone()
		{
			CronExpression cronExpression;
			try
			{
				cronExpression = new CronExpression(this.CronExpressionString);
				cronExpression.TimeZone = this.TimeZone;
			}
			catch (System.FormatException)
			{
				throw new System.Exception("Not Cloneable.");
			}
			return cronExpression;
		}
		public void OnDeserialization(object sender)
		{
			this.BuildExpression(this.cronExpressionString);
		}
		public bool Equals(CronExpression other)
		{
			return !object.ReferenceEquals(null, other) && (object.ReferenceEquals(this, other) || (object.Equals(other.cronExpressionString, this.cronExpressionString) && object.Equals(other.timeZone, this.timeZone)));
		}
		public override bool Equals(object obj)
		{
			return !object.ReferenceEquals(null, obj) && (object.ReferenceEquals(this, obj) || (!(obj.GetType() != typeof(CronExpression)) && this.Equals((CronExpression)obj)));
		}
		public override int GetHashCode()
		{
			return ((this.cronExpressionString != null) ? this.cronExpressionString.GetHashCode() : 0) * 397 ^ ((this.timeZone != null) ? this.timeZone.GetHashCode() : 0);
		}
	}
}
